#include <ESP8266WiFi.h>
#include <ArduinoJson.h>

#define LED_PIN 2        // 板载LED
#define WIFI_SSID "DDD"  // WiFi名称
#define WIFI_PASSWORD "12345678"  // WiFi密码
#define SERVER_IP "115.28.209.116"  // TCP服务器IP
#define SERVER_PORT 9801           // TCP服务器端口

// 数据包定义
#define TEMP_HUM_PACKET_LEN 8  // 温湿度数据包长度
#define ALARM_PACKET_LEN 6     // 火灾雨水数据包长度
#define UART_BAUD_RATE 9600    // 串口波特率

WiFiClient tcpClient;

// 缓冲区与状态变量
uint8_t tempHumBuf[TEMP_HUM_PACKET_LEN];
uint8_t alarmBuf[ALARM_PACKET_LEN];
int tempHumBufIdx = 0;
int alarmBufIdx = 0;
bool tempHumPacketReady = false;
bool alarmPacketReady = false;
bool firstConnect = true;

// 连接与发送计时
unsigned long lastReconnectTime = 0;
unsigned long lastSendTime = 0;
const unsigned long SEND_INTERVAL = 3000;  // 3秒发送一次

void setup() {
  pinMode(LED_PIN, OUTPUT);
  digitalWrite(LED_PIN, HIGH);  // 初始LED熄灭
  
  Serial.begin(UART_BAUD_RATE);
  connectToWiFi();  // 连接WiFi
}

void loop() {
  // 1. 维护TCP连接
  if (!tcpClient.connected()) {
    reconnectTCP();
  }
  
  // 2. 处理串口数据
  while (Serial.available()) {
    uint8_t byte = Serial.read();
    
    // 2.1 解析温湿度数据包（帧头0x55 0xAA，帧尾0xBB）
    if (tempHumBufIdx == 0 && byte == 0x55) {
      tempHumBuf[tempHumBufIdx++] = byte;
    } else if (tempHumBufIdx > 0 && tempHumBufIdx < TEMP_HUM_PACKET_LEN) {
      tempHumBuf[tempHumBufIdx++] = byte;
      if (tempHumBufIdx == TEMP_HUM_PACKET_LEN && 
          tempHumBuf[0] == 0x55 && tempHumBuf[1] == 0xAA && tempHumBuf[7] == 0xBB) {
        tempHumPacketReady = true;
      }
    } else if (tempHumBufIdx > 0) {
      tempHumBufIdx = 0;  // 重置缓冲区
    }
    
    // 2.2 解析火灾雨水数据包（帧头0x56，帧尾0xCC）
    if (alarmBufIdx == 0 && byte == 0x56) {
      alarmBuf[alarmBufIdx++] = byte;
    } else if (alarmBufIdx > 0 && alarmBufIdx < ALARM_PACKET_LEN) {
      alarmBuf[alarmBufIdx++] = byte;
      if (alarmBufIdx == ALARM_PACKET_LEN && alarmBuf[0] == 0x56 && alarmBuf[5] == 0xCC) {
        alarmPacketReady = true;
      }
    } else if (alarmBufIdx > 0) {
      alarmBufIdx = 0;  // 重置缓冲区
    }
  }
  
  // 3. 处理完整数据包
  if (tempHumPacketReady) {
    processTempHumPacket(tempHumBuf);
    tempHumPacketReady = false;
    tempHumBufIdx = 0;
  }
  if (alarmPacketReady) {
    processAlarmPacket(alarmBuf);
    alarmPacketReady = false;
    alarmBufIdx = 0;
  }
  
  // 4. 定时重发（防止断连）
  if (millis() - lastSendTime > SEND_INTERVAL && tcpClient.connected()) {
    resendData();
    lastSendTime = millis();
  }
  
  delay(10);  // 降低CPU占用
}

// 连接WiFi
void connectToWiFi() {
  WiFi.mode(WIFI_STA);
  WiFi.begin(WIFI_SSID, WIFI_PASSWORD);
  
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    digitalWrite(LED_PIN, !digitalRead(LED_PIN));  // 闪烁LED表示连接中
  }
  
  digitalWrite(LED_PIN, HIGH);  // 连接成功，LED熄灭
  if (firstConnect) {
    Serial.println("WiFi连接成功");
    firstConnect = false;
  }
}

// 重连TCP服务器
void reconnectTCP() {
  if (millis() - lastReconnectTime < 5000) return;  // 避免频繁重连
  
  lastReconnectTime = millis();
  if (tcpClient.connected()) tcpClient.stop();  // 关闭旧连接
  
  bool connected = tcpClient.connect(SERVER_IP, SERVER_PORT);
  if (connected) {
    digitalWrite(LED_PIN, LOW);
    delay(200);
    digitalWrite(LED_PIN, HIGH);
  } else {
    digitalWrite(LED_PIN, LOW);
  }
}

// 处理温湿度数据包并生成JSON
void processTempHumPacket(uint8_t* data) {
  // 校验和验证
  uint8_t checksum = 0;
  for (int i = 2; i < 6; i++) checksum += data[i];
  if (checksum != data[6]) return;
  
  // 生成JSON
  const size_t JSON_SIZE = 256;
  StaticJsonDocument<JSON_SIZE> doc;
  doc["sign"] = "9ad90d8f6224a7ae";
  doc["type"] = 1;
  
  JsonObject dataObj = doc.createNestedObject("data");
  JsonObject tempHumObj = dataObj.createNestedObject("temphum");
  tempHumObj["temp"] = (int)data[2];    // 温度值
  tempHumObj["hum"] = (int)data[3];     // 湿度值
  tempHumObj["fhum"] = (int)data[4];
  // 发送JSON
  sendJSONToServer(doc);
}

// 处理火灾雨水数据包并生成JSON
void processAlarmPacket(uint8_t* data) {
  // 校验和验证
  uint8_t checksum = 0;
  for (int i = 1; i < 4; i++) checksum += data[i];
  if (checksum != data[4]) return;
  
  // 生成JSON
  const size_t JSON_SIZE = 256;
  StaticJsonDocument<JSON_SIZE> doc;
  doc["sign"] = "9ad90d8f6224a7ae";
  doc["type"] = 1;
  
  JsonObject dataObj = doc.createNestedObject("data");
  JsonObject fireObj = dataObj.createNestedObject("fire");
  fireObj["fire"] = (bool)data[1];  // 火灾状态（布尔值）
  fireObj["rain"] = (bool)data[2];  // 雨水状态（布尔值）
  
  // 发送JSON
  sendJSONToServer(doc);
}

// 发送JSON到服务器
void sendJSONToServer(JsonDocument& doc) {
  char jsonBuf[256];
  serializeJson(doc, jsonBuf);
  Serial.println(jsonBuf);  // 打印JSON到串口（调试用）
  
  if (tcpClient.connected()) {
    tcpClient.println(jsonBuf);  // 发送到TCP服务器
    digitalWrite(LED_PIN, LOW);
    delay(100);
    digitalWrite(LED_PIN, HIGH);  // LED闪烁表示发送成功
  }
}

// 定时重发数据（防止连接断开）
void resendData() {
  // 此处可添加重发逻辑，例如重新读取传感器数据
  // 本示例中仅打印提示
  Serial.println("定时重发数据...");
}